using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace TowerClimber
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        #region Declare Variables

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D background, backgroundCopy, shading, mainMenu, gameOver;
        public Vector2 backgroundPosition, playerLastPosition, previousLinePosition;
        Player player;
        PlatformLine[] level1;
        SpriteFont spritefont;
        TimeSpan jumpTime, previousTime;
        float record, score = 0f;
        float scrollSpeed = 0.75f;
        public float gravity = 4f;
        int level, numberLines, numberPlats, platDistance = 0;
        Random RNG;
        Song song1;
        SoundEffect jumpFX, deathFX;
        bool soundPlayed = false;
        int[] platTypes;
        Screen.Type currentScreen = Screen.Type.mainMenu;
        KeyboardState previousState;

        #endregion

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferHeight = 640;
            graphics.PreferredBackBufferWidth = 500;
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            record = HighScoreManager.loadScore();
            numberLines = 12;
            level = 1;
            backgroundPosition = Vector2.Zero;
            player = new Player();
            player.position = new Vector2(250, -150);
            RNG = new Random();
            previousLinePosition = new Vector2(0,700);
            platDistance = 125;
            level1 = new PlatformLine[numberLines];
            platTypes = new int[] {0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8};
            for (int i = 0; i < numberLines; i++)
            {
                numberPlats = RNG.Next(4,6);
                level1[i] = new PlatformLine();
                level1[i].generatePlatLine(numberPlats, previousLinePosition, (600 / numberPlats), platTypes, RNG.Next(-4, 4), RNG, level);
                previousLinePosition.Y -= platDistance;
            }
            jumpTime = TimeSpan.FromMilliseconds(500);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            background = Content.Load<Texture2D>("brickwall");
            backgroundCopy = background;
            spritefont = Content.Load<SpriteFont>("SpriteFont1");
            shading = Content.Load<Texture2D>("lighting");
            song1 = Content.Load<Song>("underworld");
            jumpFX = Content.Load<SoundEffect>("Mario Jump");
            deathFX = Content.Load<SoundEffect>("death");
            mainMenu = Content.Load<Texture2D>("menu");
            gameOver = Content.Load<Texture2D>("gameOver");
            for (int i = 0; i < numberLines; i++)
            {
                level1[i].platLineLoadContent(this.Content);
            }

            player.initializePlayer();

            spriteBatch = new SpriteBatch(GraphicsDevice);

        }

        protected override void UnloadContent()
        {

        }

        protected override void Update(GameTime gameTime)
        {
            switch (currentScreen)
            {
                case Screen.Type.gamePlay:
                    {
                        #region Audio
                        if (MediaPlayer.State == MediaState.Stopped)
                        {
                            if (soundPlayed == false)
                            {
                                MediaPlayer.Play(song1);
                            }
                        }

                        #endregion

                        #region background
                        backgroundPosition.Y += scrollSpeed;
                        if (backgroundPosition.Y > background.Height)
                        {
                            backgroundPosition = Vector2.Zero;
                        }
                        #endregion

                        #region KeyboardInput

                        player.horizontalSpeed = 0;
                        player.verticalSpeed = 0;
                        if (player.onGround == false)
                        {
                            if (player.jumpingUp == false)
                            {
                                player.verticalSpeed = gravity;
                            }
                        }
                        if (player.jumpingUp == true)
                        {
                            player.verticalSpeed = -5f;
                        }

                        if (Keyboard.GetState().IsKeyDown(Keys.Left))
                        {
                            player.horizontalSpeed = -player.moveSpeed;
                            player.facingLeft = true;
                        }

                        if (Keyboard.GetState().IsKeyDown(Keys.Right))
                        {
                            player.horizontalSpeed = player.moveSpeed;
                            player.facingLeft = false;
                        }

                        if (Keyboard.GetState().IsKeyDown(Keys.Space))
                        {
                            if ((player.onGround == true) && (gameTime.TotalGameTime - jumpTime > previousTime))
                            {
                                jumpFX.Play();
                                player.jumpingUp = true;
                                previousTime = gameTime.TotalGameTime;

                            }

                        }

                        if ((Keyboard.GetState().IsKeyDown(Keys.P)) && (previousState.IsKeyUp(Keys.P)))
                        {
                            currentScreen = Screen.Type.Pause;
                        }

                        if (gameTime.TotalGameTime - jumpTime > previousTime)
                        {
                            player.jumpingUp = false;
                        }

                        #endregion

                        #region UpdatePlayer

                        player.updatePlayer(this.Content, gameTime);

                        if (player.position.Y > graphics.PreferredBackBufferHeight)
                        {
                            player.alive = false;
                        }

                        if (player.position.X > graphics.PreferredBackBufferWidth + 50)
                        {
                            player.alive = false;
                        }
                        if (player.position.X < -100)
                        {
                            player.alive = false;
                        }

                        for (int i = 0; i < numberLines; i++)
                        {
                            level1[i].updatePlatLine(player, playerLastPosition, platDistance, numberLines, RNG, level, this.Content);
                        }

                        #endregion

                        #region Collision

                        player.onGround = false;

                        for (int i = 0; i < numberLines; i++)
                        {
                            level1[i].updateCollision(player, playerLastPosition);
                        }


                        #endregion

                        playerLastPosition = player.position;

                        #region Scroll

                        player.position.Y += scrollSpeed;

                        for (int i = 0; i < numberLines; i++)
                        {
                            level1[i].scrollPlats(scrollSpeed);
                        }

                        #endregion

                        #region Score and Difficulty


                        if (score >= 1000 * level)
                        {
                            scrollSpeed += 0.25f;
                            if (soundPlayed == false)
                            {
                                level++;
                            }
                        }

                        if (player.alive == true)
                        {
                            score += (scrollSpeed / 2);
                        }
                        else
                        {
                            scrollSpeed = 0;
                            if (soundPlayed == false)
                            {
                                MediaPlayer.Stop();
                                deathFX.Play();
                                soundPlayed = true;
                                player.position = new Vector2(1500, 1500);
                            }
                        }

                        #endregion
                        break;
                    }
                case Screen.Type.mainMenu:
                    {
                        if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                        {
                            currentScreen = Screen.Type.gamePlay;

                        }
                        break;
                    }
                case Screen.Type.gameOver:
                    {
                        if (Keyboard.GetState().IsKeyDown(Keys.R))
                        {
                            player.alive = true;
                            soundPlayed = false;
                            score = 0;
                            level = 1;
                            scrollSpeed = 0.75f;
                            player.position = new Vector2(250, 0);
                            currentScreen = Screen.Type.gamePlay;
                        }
                        break;
                    }
                case Screen.Type.Pause:
                    {
                        if ((Keyboard.GetState().IsKeyDown(Keys.P)) && (previousState.IsKeyUp(Keys.P)))
                        {
                            currentScreen = Screen.Type.gamePlay;
                        }
                        break;
                    }
            }

            previousState = Keyboard.GetState();
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();

            if ((currentScreen == Screen.Type.gamePlay) || (currentScreen == Screen.Type.Pause))
            {

                spriteBatch.Draw(background, backgroundPosition, Color.White);
                spriteBatch.Draw(backgroundCopy, new Vector2(backgroundPosition.X, backgroundPosition.Y - background.Height), Color.White);
                player.drawPlayer(spriteBatch);
                for (int i = 0; i < numberLines; i++)
                {
                    level1[i].drawPlatLine(spriteBatch);
                }
                spriteBatch.Draw(shading, Vector2.Zero, Color.White);
                spriteBatch.DrawString(spritefont, "Score: " + (int)score + "Level: " + level, Vector2.Zero, Color.White);
                spriteBatch.DrawString(spritefont, "Record: " + (int)record, new Vector2(0, 30), Color.White);
                if (player.alive == false)
                {
                    if (score > record)
                    {
                        record = score;
                        HighScoreManager.saveScore(record);
                    }
                    currentScreen = Screen.Type.gameOver;
                }
                if (currentScreen == Screen.Type.Pause) spriteBatch.DrawString(spritefont, "JOGO PAUSADO", new Vector2(188, 300), Color.White);
            }

            if (currentScreen == Screen.Type.mainMenu)
            {
                spriteBatch.Draw(mainMenu, Vector2.Zero, Color.White);
            }

            if (currentScreen == Screen.Type.gameOver)
            {
                spriteBatch.Draw(gameOver, Vector2.Zero, Color.White);
                spriteBatch.DrawString(spritefont, "Pontuacao Final:" + (int)score, new Vector2(142, 350), Color.White);
                spriteBatch.DrawString(spritefont, "Pontuacao Recorde:" + (int)record, new Vector2(142, 395), Color.White);
                spriteBatch.DrawString(spritefont, "Pressione R para tentar novamente", new Vector2(76, 440), Color.White);
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
